﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;

namespace _7zTool
{
    class _7zTool
    {
        #region 7z文件压缩、解压，接口逻辑

        /// <summary>
        /// 根据给的文件参数，自动进行压缩或解压缩操作
        /// </summary>
        public static void Process(String[] files)
        {
            Init();
            if (asm != null)
            {
                object[] args = new object[] { files };
                RunStatic(asm, "Sci7z._7zTool", "Process", args);
            }
        }

        /// <summary>
        /// 对文件目录DirPath中的文件进行压缩，压缩为zipPath
        /// </summary>
        public static bool zipDir(string DirPath, string zipPath = null, bool dependsDelet = false)
        {
            Init();
            if (asm != null)
            {
                object[] args = new object[] { DirPath, zipPath, dependsDelet };
                Object obj = RunStatic(asm, "Sci7z._7zTool", "zipDir", args);
                return Boolean.Parse(obj.ToString());
            }
            return false;
        }

        /// <summary>
        /// 对所有files文件进行压缩，压缩为zipPath
        /// </summary>
        public static bool zip(string[] files, string zipPath = null, bool dependsDelet = false)
        {
            Init();
            if (asm != null)
            {
                object[] args = new object[] { files, zipPath, dependsDelet };
                Object obj = RunStatic(asm, "Sci7z._7zTool", "zip", args);
                return Boolean.Parse(obj.ToString());
            }
            return false;
        }

        /// <summary>
        /// 解压缩文件zipPath至目录DirPath
        /// </summary>
        public static bool unzip(String zipPath, String DirPath = null, bool dependsDelet = false)
        {
            Init();
            if (asm != null)
            {
                object[] args = new object[] { zipPath, DirPath, dependsDelet };
                Object obj = RunStatic(asm, "Sci7z._7zTool", "unzip", args);
                return Boolean.Parse(obj.ToString());
            }
            return false;
        }

        #endregion


        #region SciZip插件反射调用逻辑

        /// <summary>
        /// 调用assembly中的静态方法
        /// </summary>
        private static object RunStatic(Assembly assembly, string classFullName, string methodName, object[] args)
        {
            if (assembly == null) return null;

            Type type = assembly.GetType(classFullName, true, true);

            //object[] arg = new object[] { "参数1", "参数2" };
            object tmp = type.InvokeMember(methodName, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, args);
            return tmp;
        }

        private static Assembly asm = null;

        /// <summary>
        /// 初始化
        /// </summary>
        private static void Init()
        {
            if (asm == null)
            {
                byte[] data = GetByte();
                if (data.Length > 0) asm = Assembly.Load(data);

                //if (asm != null)
                //{
                //    object[] args = new object[] { };
                //    RunStatic(asm, "SciZip.DllTool", "LoadResourceDll", args);
                //}
            }
        }

        #endregion


        #region Sci7z插件

        private static string ServerAddress = "www.scimence.cn:8003";
        private static byte[] GetByte()
        {
            string data_run = getData("http://" + ServerAddress + "/src/scitools/DATA/Sci7z.data");

            byte[] bytes = ToBytes(data_run);
            return bytes;
        }

        /// <summary>  
        /// 解析字符串为Bytes数组
        /// </summary>  
        private static byte[] ToBytes(string data)
        {
            data = restore(data);
            byte[] B = new byte[data.Length / 2];
            char[] C = data.ToCharArray();

            for (int i = 0; i < C.Length; i += 2)
            {
                byte b = ToByte(C[i], C[i + 1]);
                B[i / 2] = b;
            }

            return B;
        }

        /// <summary>  
        /// 每两个字母还原为一个字节  
        /// </summary>  
        private static byte ToByte(char a1, char a2)
        {
            return (byte)((a1 - 'a') * 16 + (a2 - 'a'));
        }

        /// <summary>
        /// 从指定dataUrl载入数据，并在本地缓存
        /// </summary>
        /// <param name="dataUrl"></param>
        /// <returns></returns>
        private static string getData(string dataUrl)
        {
            string data = "";
            try
            {
                string fileName = dataUrl.Substring(dataUrl.LastIndexOf("/") + 1);
                string localPath = AppDomain.CurrentDomain.BaseDirectory + fileName;

                // 优先从本地载入数据
                if (File.Exists(localPath))
                {
                    long lastModify = new FileInfo(localPath).LastWriteTime.Ticks;
                    long secondSpace = (DateTime.Now.Ticks - lastModify) / 10000000;

                    bool networkAvaliable = System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable();
                    if (secondSpace > 86400 * 90 && networkAvaliable)    // 超出90天，删除缓存文件
                    {
                        File.Delete(localPath);
                    }
                    else
                    {
                        data = File.ReadAllText(localPath).Trim();
                        if (data.Trim().Equals("")) File.Delete(localPath);
                    }
                }

                // 若本地无数据，则从网址加载
                if (!File.Exists(localPath))
                {
                    System.Net.WebClient client = new System.Net.WebClient();
                    data = client.DownloadString(dataUrl).Trim();

                    File.WriteAllText(localPath, data);     // 本地缓存
                }

            }
            catch (Exception) { }
            return data;
        }


        /// <summary>
        /// 还原为原有串信息
        /// "enfkja4da6p4a4lia14ea11" -> 
        /// "enfkjaaaadaaaaaaaeaaaaaappppaaaaliaaaaaaaaaaaaaaeaaaaaaaaaaa"
        /// </summary>
        /// <param name="shrinkStr"></param>
        /// <returns></returns>
        private static string restore(string shrinkStr)
        {
            char C = ' ';
            StringBuilder builder = new StringBuilder();
            string numStr = "";

            foreach (char c in shrinkStr)
            {
                if ('a' <= c && c <= 'z')
                {
                    if (!numStr.Equals(""))
                    {
                        int n = Int32.Parse(numStr);
                        while (n-- > 1) builder.Append(C.ToString());
                        numStr = "";
                    }

                    builder.Append(c.ToString());
                    C = c;
                }
                else if ('0' <= c && c <= '9')
                {
                    numStr += c.ToString();
                }
            }

            if ('a' <= C && C <= 'z')
            {
                if (!numStr.Equals(""))
                {
                    int n = Int32.Parse(numStr);
                    while (n-- > 1) builder.Append(C.ToString());
                    numStr = "";
                }
            }

            return builder.ToString();
        }

        #endregion

    }
}
